#pragma once

using namespace hsql;

// 解析sql类型
inline SqlKind detectSqlKind(const std::string& sql) {
    SQLParserResult res;
    SQLParser::parse(sql, &res);
    if (!res.isValid() || res.size() < 1) return SqlKind::Unknown;

    const auto* stmt = res.getStatement(0);
    switch (stmt->type()) {
        case kStmtCreate: return SqlKind::Create;
        case kStmtInsert: return SqlKind::Insert;
        case kStmtUpdate: return SqlKind::Update;
        case kStmtSelect: return SqlKind::Select;
        case kStmtDelete: return SqlKind::Delete;
        default:          return SqlKind::Unknown;
    }
}

inline bool parseSql(const std::string& sql, SQLParserResult& result) {
    SQLParser::parse(sql, &result);           // 注意：不是 parseSQLString
    return result.isValid() && result.size() == 1;
}


inline FieldType mapSqlTypeToFieldType(hsql::DataType t) {
    using namespace hsql;
    switch (t) {
        case DataType::INT:
        case DataType::BIGINT:   return FieldType::INT;
        case DataType::CHAR:
        case DataType::VARCHAR:
        case DataType::TEXT:     return FieldType::STRING;
        case DataType::DATETIME: return FieldType::DATETIME;
        default:                 return FieldType::STRING;
    }
}

inline void setFieldName(FieldInfo& f, const std::string& name) {
    std::memset(f.name, 0, sizeof(f.name));
    std::strncpy(f.name, name.c_str(), sizeof(f.name) - 1);
}

inline bool parseCreateTableSql(const std::string& sql,
                                std::string& tableName,
                                std::vector<FieldInfo>& outFields) {
    hsql::SQLParserResult res;
    if (!parseSql(sql, res)) return false;

    const auto* stmt = dynamic_cast<const hsql::CreateStatement*>(res.getStatement(0));
    if (!stmt) return false;

    tableName = stmt->tableName;   // const char*
    outFields.clear();

    if (stmt->columns) {           // vector<ColumnDefinition*>*
        for (const auto* col : *stmt->columns) {
            FieldInfo f{};
            setFieldName(f, col->name);                    // 列名
            f.type = mapSqlTypeToFieldType(col->type.data_type);  // 类型

            // 主键
            if (col->column_constraints) {
                for (const auto cc : *col->column_constraints) {
                    if (cc == hsql::ConstraintType::PrimaryKey) {
                        // col->name 就是主键列
                        f.isPrimary = true;
                        f.autoIncrement = true;
                    }
                }
            }
            outFields.push_back(f);
        }
    }
    return true;
}


static inline std::unordered_map<std::string, size_t>
buildNameToIndex(const std::vector<FieldInfo>& schema) {
    std::unordered_map<std::string, size_t> m;
    for (size_t i = 0; i < schema.size(); ++i) m[std::string(schema[i].name)] = i;
    return m;
}

extern bool parseDatetimeStringTo5(const char* ts19, uint8_t out5[5]);

inline bool buildCellsFromInsert(const std::string& sql,
                                 const std::vector<FieldInfo>& schema,
                                 std::string& outTable,
                                 std::vector<Cell>& outCells) {
    SQLParserResult res;
    SQLParser::parse(sql, &res);
    if (!res.isValid() || res.size() != 1) {
        std::cerr << "parse error: "
                  << (res.errorMsg() ? res.errorMsg() : "unknown")
                  << " at " << res.errorLine() << ":" << res.errorColumn() << std::endl;
        return false;
    }

    const auto* ins = dynamic_cast<const InsertStatement*>(res.getStatement(0));
    if (!ins) return false;

    outTable = ins->tableName ? ins->tableName : "";
    auto nameToIdx = buildNameToIndex(schema);

    // 列顺序
    std::vector<size_t> targetIdx;
    if (ins->columns && !ins->columns->empty()) {
        targetIdx.reserve(ins->columns->size());
        for (auto* cname : *ins->columns) {
            auto it = nameToIdx.find(cname);
            if (it == nameToIdx.end()) return false;
            targetIdx.push_back(it->second);
        }
    } else {
        targetIdx.resize(schema.size());
        std::iota(targetIdx.begin(), targetIdx.end(), 0);
    }

    // 取一行 values（多行你可自己循环 ins->valuesLists）
    const std::vector<Expr*>* row = nullptr;
    if (ins->values && !ins->values->empty()) row = ins->values;
//    else if (ins->valuesLists && !ins->valuesLists->empty() && (*ins->valuesLists)[0])
//        row = (*ins->valuesLists)[0];
    if (!row) return false;

    // 先全置空，按 schema 大小准备
    outCells.assign(schema.size(), Cell{});

    auto putValue = [&](size_t colIdx, const hsql::Expr* e) -> bool {
        Cell c{};
        c.type = schema[colIdx].type;

        if (!e || e->isType(hsql::kExprLiteralNull)) {
            c.is_null = true;
            outCells[colIdx] = std::move(c);
            return true;
        }

        c.is_null = false;
        switch (c.type) {
            case FieldType::INT:
                if (e->isType(hsql::kExprLiteralInt)) {
                    c.i64 = static_cast<int64_t>(e->ival);
                } else if (e->isType(hsql::kExprLiteralFloat)) {
                    c.i64 = static_cast<int64_t>(e->fval);
                } else if (e->isType(hsql::kExprLiteralString)) {
                    c.i64 = std::stoll(e->name);  // 允许 '123'
                } else {
                    return false; // 不支持的表达式
                }
                break;

            case FieldType::STRING:
                if (e->isType(hsql::kExprLiteralString)) {
                    c.str = e->name;
                } else if (e->isType(hsql::kExprLiteralInt)) {
                    c.str = std::to_string(e->ival);
                } else if (e->isType(hsql::kExprLiteralFloat)) {
                    c.str = std::to_string(e->fval);
                } else {
                    return false; // 不支持的表达式
                }
                break;

            case FieldType::DATETIME: {
                if (!e->isType(hsql::kExprLiteralString)) return false; // 仅支持 "YYYY-MM-DD HH:MM:SS"
                std::string s = e->name;
                if (!parseDatetimeStringTo5(s.c_str(), c.datetime)) return false;
                break;
            }

            default:
                return false;
        }

        outCells[colIdx] = std::move(c);
        return true;
    };

    // 按列顺序填充值
    const size_t n = std::min(targetIdx.size(), row->size());
    for (size_t i = 0; i < n; ++i) {
        putValue(targetIdx[i], (*row)[i]);
    }
    // 未提供的列保持 is_null = true（或你自定默认）

    return true;
}

// select
static inline std::string dequoteIdent(const char* name) {
    if (!name) return {};
    std::string s(name);
    if (s.size() >= 2) {
        if ((s.front()=='`' && s.back()=='`') || (s.front()=='"' && s.back()=='"'))
            return s.substr(1, s.size()-2);
    }
    return s;
}
static inline size_t findColIndex(const std::vector<FieldInfo>& schema, const std::string& col){
    for (size_t i=0;i<schema.size();++i)
        if (col == std::string(schema[i].name)) return i;
    return static_cast<size_t>(-1);
}
static inline bool mapOp(OperatorType t, CompareOp& out){
    switch (t){
        case kOpEquals:      out = CompareOp::EQ;            return true;
        case kOpNotEquals:   out = CompareOp::NOT_EQ;        return true;
        case kOpLess:        out = CompareOp::LESS;          return true;
        case kOpLessEq:      out = CompareOp::LESS_EQUAL;    return true;
        case kOpGreater:     out = CompareOp::GREATER;       return true;
        case kOpGreaterEq:   out = CompareOp::GREATER_EQUAL; return true;
        default: return false;
    }
}
static inline CompareOp invertForSwap(CompareOp op){
    switch (op){
        case CompareOp::LESS:          return CompareOp::GREATER;
        case CompareOp::LESS_EQUAL:    return CompareOp::GREATER_EQUAL;
        case CompareOp::GREATER:       return CompareOp::LESS;
        case CompareOp::GREATER_EQUAL: return CompareOp::LESS_EQUAL;
        default: return op; // EQ/NOT_EQ 不变
    }
}
static inline void collectAndNodes(const Expr* e, std::vector<const Expr*>& out){
    if (!e) return;
    if (e->type == kExprOperator && e->opType == kOpAnd){
        collectAndNodes(e->expr, out);
        collectAndNodes(e->expr2, out);
    } else {
        out.push_back(e);
    }
}
inline std::string getTableName(const std::string& sql) {
    hsql::SQLParserResult res;
    if (!parseSql(sql, res)) return "";
    const hsql::SQLStatement* s = res.getStatement(0);
    switch (s->type()) {
        case hsql::kStmtCreate: {
            const auto* st = dynamic_cast<const hsql::CreateStatement*>(s);
            return (st && st->tableName) ? dequoteIdent(st->tableName) : "";
        }
        case hsql::kStmtSelect: {
            const auto* st = dynamic_cast<const hsql::SelectStatement*>(s);
            if (!st || !st->fromTable) return "";
            const auto* t = st->fromTable;
            return (t->type == hsql::kTableName && t->name) ? dequoteIdent(t->name) : "";
        }
        case hsql::kStmtInsert: {
            const auto* st = dynamic_cast<const hsql::InsertStatement*>(s);
            return (st && st->tableName) ? dequoteIdent(st->tableName) : "";
        }
        case hsql::kStmtUpdate: {
            const auto* st = dynamic_cast<const hsql::UpdateStatement*>(s);
            if (!st || !st->table) return "";
            const auto* t = st->table;
            return (t->type == hsql::kTableName && t->name) ? dequoteIdent(t->name) : "";
        }
        case hsql::kStmtDelete: {
            const auto* st = dynamic_cast<const hsql::DeleteStatement*>(s);
            return (st && st->tableName) ? dequoteIdent(st->tableName) : "";
        }
        default:
            return "";
    }
}






// v2
// 将字面量 Expr 转为 Cell（和你现有 where 的值构造逻辑保持一致）
static inline bool literalToCell(const Expr* lit, FieldType type, Cell& out) {
    if (!lit) return false;
    out.type = type;
    if (lit->isType(kExprLiteralNull)) { out.is_null = true; return true; }
    out.is_null = false;
    switch (type) {
        case FieldType::INT:
            if (lit->isType(kExprLiteralInt))        out.i64 = static_cast<int64_t>(lit->ival);
            else if (lit->isType(kExprLiteralFloat)) out.i64 = static_cast<int64_t>(lit->fval);
            else if (lit->isType(kExprLiteralString)) out.i64 = std::stoll(lit->name);
            else return false;
            return true;
        case FieldType::STRING:
            if (lit->isType(kExprLiteralString))      out.str = lit->name;
            else if (lit->isType(kExprLiteralInt))    out.str = std::to_string(lit->ival);
            else if (lit->isType(kExprLiteralFloat))  out.str = std::to_string(lit->fval);
            else return false;
            return true;
        case FieldType::DATETIME:
            if (!lit->isType(kExprLiteralString)) return false;
            return parseDatetimeStringTo5(lit->name, out.datetime);
    }
    return false;
}

// 通用：从 where Expr 构建 filters（SELECT/UPDATE/DELETE 复用）
static inline bool buildFiltersFromWhereExpr(const Expr* where,
                                             const std::vector<FieldInfo>& schema,
                                             std::vector<SqlFilter>& outFilters) {
    outFilters.clear();
    if (!where) return true;

    std::vector<const Expr*> nodes;
    collectAndNodes(where, nodes);

    for (const Expr* n : nodes) {
        if (!(n && n->type==kExprOperator)) return false;

        CompareOp op;
        if (!mapOp(n->opType, op)) return false;

        const Expr* L = n->expr;
        const Expr* R = n->expr2;
        if (!L || !R) return false;

        const Expr* col = nullptr;
        const Expr* lit = nullptr;
        CompareOp useOp = op;
        if (L->type == kExprColumnRef) { col = L; lit = R; }
        else if (R->type == kExprColumnRef) { col = R; lit = L; useOp = invertForSwap(op); }
        else return false;

        std::string colName = dequoteIdent(col->name);
        size_t idx = findColIndex(schema, colName);
        if (idx == static_cast<size_t>(-1)) return false;

        SqlFilter f{};
        f.type = useOp;
        f.colIndex = idx;
        f.value.type = schema[idx].type;
        if (!literalToCell(lit, f.value.type, f.value)) return false;

        outFilters.push_back(std::move(f));
    }
    return true;
}

inline bool buildFiltersFromSelect_delete(const std::string& sql,
                                   const std::vector<FieldInfo>& schema,
                                   std::string& outTable,
                                   std::vector<SqlFilter>& outFilters) {
    SQLParserResult res;
    SQLParser::parse(sql, &res);
    if (!res.isValid() || res.size()!=1) return false;

    const auto* sel = dynamic_cast<const SelectStatement*>(res.getStatement(0));
    if (!sel || !sel->fromTable || sel->fromTable->type != kTableName) return false;

    outTable = sel->fromTable->name ? sel->fromTable->name : "";

    outFilters.clear();

    // 无 where → 空过滤（相当于全表）
    const Expr* where = sel->whereClause;
    if (!where) return true;

    // 展平 AND
    std::vector<const Expr*> nodes;
    collectAndNodes(where, nodes);

    for (const Expr* n : nodes) {
        if (!(n && n->type==kExprOperator)) return false;

        CompareOp op;
        if (!mapOp(n->opType, op)) return false;

        const Expr* L = n->expr;
        const Expr* R = n->expr2;
        if (!L || !R) return false;

        // 列-字面量识别，必要时反转运算符
        const Expr* col = nullptr;
        const Expr* lit = nullptr;
        CompareOp useOp = op;
        if (L->type == kExprColumnRef) { col = L; lit = R; }
        else if (R->type == kExprColumnRef) { col = R; lit = L; useOp = invertForSwap(op); }
        else return false;

        std::string colName = dequoteIdent(col->name);
        size_t idx = findColIndex(schema, colName);
        if (idx == static_cast<size_t>(-1)) return false;

        SqlFilter f{};
        f.type = useOp;
        f.colIndex = idx;
        f.value.type = schema[idx].type;
        if (!literalToCell(lit, f.value.type, f.value)) return false;

        outFilters.push_back(std::move(f));
    }
    return true;
}

inline bool buildWhereFromSelectSql(const std::string& sql,
                                    const std::vector<FieldInfo>& schema,
                                    std::vector<SqlFilter>& outWhere) {
    SQLParserResult res;
    SQLParser::parse(sql, &res);
    if (!res.isValid() || res.size()!=1) return false;
    const auto* sel = dynamic_cast<const SelectStatement*>(res.getStatement(0));
    if (!sel) return false;
    return buildFiltersFromWhereExpr(sel->whereClause, schema, outWhere);
}

// 仅构建 DELETE 的 where（不返回表名）
inline bool buildWhereFromDeleteSql(const std::string& sql,
                                    const std::vector<FieldInfo>& schema,
                                    std::vector<SqlFilter>& outWhere) {
    SQLParserResult res;
    SQLParser::parse(sql, &res);
    if (!res.isValid() || res.size()!=1) return false;
    const auto* stmt = dynamic_cast<const DeleteStatement*>(res.getStatement(0));
    if (!stmt) return false;
    return buildFiltersFromWhereExpr(stmt->expr, schema, outWhere);
}


// UPDATE：提取 SET 列表与 WHERE（不返回表名）
// 注意：UpdateClause::column 是 char* 列名
inline bool buildUpdateSetsAndWhereFromSql(const std::string& sql,
                                           const std::vector<FieldInfo>& schema,
                                           std::vector<UpdateSetItem>& outSets,
                                           std::vector<SqlFilter>& outWhere) {
    SQLParserResult res;
    SQLParser::parse(sql, &res);
    if (!res.isValid() || res.size()!=1) return false;
    const auto* stmt = dynamic_cast<const UpdateStatement*>(res.getStatement(0));
    if (!stmt) return false;

    outSets.clear();
    outWhere.clear();

    if (stmt->updates) {
        for (const auto* uc : *stmt->updates) {
            if (!uc || !uc->column || !uc->value) return false;

            // 列名来自 char*
            std::string colName = dequoteIdent(uc->column);  // 若无 dequoteIdent，可用: std::string(uc->column)
            size_t idx = findColIndex(schema, colName);
            if (idx == static_cast<size_t>(-1)) return false;

            UpdateSetItem item{};
            item.colIndex = idx;
            item.value.type = schema[idx].type;
            if (!literalToCell(uc->value, item.value.type, item.value)) return false; // 仅支持字面量
            outSets.push_back(std::move(item));
        }
    }

    return buildFiltersFromWhereExpr(stmt->where, schema, outWhere);
}